package ac.neec.mio.ui.activity;

import java.util.List;
import java.util.UUID;

import ac.neec.core.ble.service.BluetoothLeService;
import ac.neec.core.ble.util.BleUuid;
import ac.neec.mio.R;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.WindowManager;

public abstract class BLEActivity extends UnBackStackActivity {
	public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
	public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
	private final static String TAG = BLEActivity.class.getSimpleName();
	protected final ServiceConnection mServiceConnection = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName componentName, IBinder service) {
			mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
			if (!mBluetoothLeService.initialize()) {
				Log.e(TAG, "Unable to initialize Bluetooth");
				finish();
			}
			// Automatically connects to the device upon successful start-up initialization.
			boolean b = mBluetoothLeService.connect(mBluetoothDevice.getAddress());
			//            mBluetoothLeService.readCharacteristic(new BluetoothGattCharacteristic(UUID.fromString(BleUuid.CHAR_HEART_RATE_MEASUREMENT), BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ));
			//            mBluetoothLeService.readCharacteristic(new BluetoothGattCharacteristic(UUID.fromString(BleUuid.CHAR_HEART_RATE_MEASUREMENT), BluetoothGattCharacteristic.PROPERTY_NOTIFY, 0));
			notifyServiceConnecttion(b);
		}

		@Override
		public void onServiceDisconnected(ComponentName componentName) {
			mBluetoothLeService = null;
		}
	};
	protected final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			final String action = intent.getAction();
			if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
				mConnected = true;
				updateConnectionState(R.string.connected);
				invalidateOptionsMenu();
				//                displayData( intent.getStringExtra( BluetoothLeService.EXTRA_DATA ) );
			} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
				mConnected = false;
				updateConnectionState(R.string.disconnected);
				invalidateOptionsMenu();
				//                displayData( intent.getStringExtra( BluetoothLeService.EXTRA_DATA ) );
				clearUI();
			} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
				// Show all the supported services and characteristics on the user interface.
				//            	displayGattServices(mBluetoothLeService.getSupportedGattServices());
				//            	displayData( intent.getStringExtra( BluetoothLeService.EXTRA_DATA ) );
//				              Toast.makeText( getApplicationContext(), "ACTION DISCOVERED", 0 ).show();
			} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
				displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
			}
		}
	};
	protected String mDeviceName;
	protected String mDeviceAddress;
	protected BluetoothDevice mBluetoothDevice;
	protected BluetoothLeService mBluetoothLeService;
	protected boolean mConnected = false;

	//	protected BluetoothGattCharacteristic mNotifyCharacteristic = new BluetoothGattCharacteristic();

	protected static IntentFilter makeGattUpdateIntentFilter() {
		final IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
		intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
		intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
		intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
		return intentFilter;
	}

	protected void setupReadCharacteristic() {
		List<BluetoothGattService> gatts = mBluetoothLeService.getSupportedGattServices();
		for (BluetoothGattService item : gatts) {
			if (item.getUuid().toString().equals(BleUuid.SERVICE_HEART_RATE)) {
				BluetoothGattCharacteristic characteristic = item.getCharacteristic(UUID
						.fromString(BleUuid.CHAR_HEART_RATE_MEASUREMENT));
				mBluetoothLeService.readCharacteristic(characteristic);
			}
		}
	}
	protected void onCreate(Bundle savedStateInstance){
		super.onCreate(savedStateInstance);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
	}

	protected void setupOnCreate() {
		final Intent intent = getIntent();
		mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
		mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
		// Sets up UI references.
		getActionBar().setTitle(mDeviceName);
		getActionBar().setDisplayHomeAsUpEnabled(true);
		//        Intent gattServiceIntent = new Intent( this, BluetoothLeService.class );
		//        bindService( gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE );

	}

	protected void setupOnResume() {
		registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
		if (mBluetoothLeService != null) {
			final boolean result = mBluetoothLeService.connect(mDeviceAddress);
			Log.d(TAG, "Connect request result=" + result);
		}
	}

	protected void setupOnPause() {
		unregisterReceiver(mGattUpdateReceiver);
	}

	protected void setupOnDestroy() {
		unbindService(mServiceConnection);
		mBluetoothLeService.close();
		mBluetoothLeService.disconnect();
		mBluetoothLeService = null;
	}

	protected void setupBLEConnect(BluetoothDevice device, BLEActivity activity) {
		mBluetoothDevice = device;
		mDeviceAddress = device.getAddress();
		//        mBluetoothLeService =
		Intent gattServiceIntent = new Intent(activity, BluetoothLeService.class);
		bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
	}

	protected abstract void updateConnectionState(final int resourceId);

	protected abstract void clearUI();

	protected abstract void displayData(String data);

	protected abstract void notifyServiceConnecttion(boolean flag);

}
